package controllers

import (
	"chuanyou1/models"
	"encoding/json"
	"errors"
	"log"
	"strconv"
	"strings"
	"time"

	beego "github.com/beego/beego/v2/server/web"
	"github.com/gorilla/websocket"
)

// 学生的接口
type ClassmatesController struct {
	beego.Controller
}

// URLMapping ...
func (c *ClassmatesController) URLMapping() {
	c.Mapping("Post", c.Post)
	c.Mapping("GetOne", c.GetOne)
	c.Mapping("GetAll", c.GetAll)
	c.Mapping("Put", c.Put)
	c.Mapping("Delete", c.Delete)
}

// Post ...
// @Title Post
// @Description create Classmates
// @Param	body		body 	models.Classmates	true		"body for Classmates content"
// @Success 201 {int} models.Classmates
// @Failure 403 body is empty
// @router / [post]
func (c *ClassmatesController) Post() {
	var v models.Classmates
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil {
		if _, err := models.AddClassmates(&v); err == nil {
			c.Ctx.Output.SetStatus(201)
			c.Data["json"] = v
		} else {
			c.Data["json"] = err.Error()
		}
	} else {
		c.Data["json"] = err.Error()
	}
	c.ServeJSON()
}

// GetOne ...
// @Title Get One
// @Description get Classmates by id
// @Param	id		path 	string	true		"The key for staticblock"
// @Success 200 {object} models.Classmates
// @Failure 403 :id is empty
// @router /:id [get]
func (c *ClassmatesController) GetOne() {
	idStr := c.Ctx.Input.Param(":id")
	id, _ := strconv.Atoi(idStr)
	v, err := models.GetClassmatesById(id)
	if err != nil {
		c.Data["json"] = err.Error()
	} else {
		c.Data["json"] = v
	}
	c.ServeJSON()
}

// GetAll ...
// @Title Get All
// @Description get Classmates
// @Param	query	query	string	false	"Filter. e.g. col1:v1,col2:v2 ..."
// @Param	fields	query	string	false	"Fields returned. e.g. col1,col2 ..."
// @Param	sortby	query	string	false	"Sorted-by fields. e.g. col1,col2 ..."
// @Param	order	query	string	false	"Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..."
// @Param	limit	query	string	false	"Limit the size of result set. Must be an integer"
// @Param	offset	query	string	false	"Start position of result set. Must be an integer"
// @Success 200 {object} models.Classmates
// @Failure 403
// @router / [get]
func (c *ClassmatesController) GetAll() {
	var fields []string
	var sortby []string
	var order []string
	var query = make(map[string]string)
	var limit int64 = 10
	var offset int64

	// fields: col1,col2,entity.col3
	if v := c.GetString("fields"); v != "" {
		fields = strings.Split(v, ",")
	}
	// limit: 10 (default is 10)
	if v, err := c.GetInt64("limit"); err == nil {
		limit = v
	}
	// offset: 0 (default is 0)
	if v, err := c.GetInt64("offset"); err == nil {
		offset = v
	}
	// sortby: col1,col2
	if v := c.GetString("sortby"); v != "" {
		sortby = strings.Split(v, ",")
	}
	// order: desc,asc
	if v := c.GetString("order"); v != "" {
		order = strings.Split(v, ",")
	}
	// query: k:v,k:v
	if v := c.GetString("query"); v != "" {
		for _, cond := range strings.Split(v, ",") {
			kv := strings.SplitN(cond, ":", 2)
			if len(kv) != 2 {
				c.Data["json"] = errors.New("Error: invalid query key/value pair")
				c.ServeJSON()
				return
			}
			k, v := kv[0], kv[1]
			query[k] = v
		}
	}

	l, err := models.GetAllClassmates(query, fields, sortby, order, offset, limit)
	if err != nil {
		c.Data["json"] = err.Error()
	} else {
		c.Data["json"] = l
	}
	c.ServeJSON()
}

// Put ...
// @Title Put
// @Description update the Classmates
// @Param	id		path 	string	true		"The id you want to update"
// @Param	body		body 	models.Classmates	true		"body for Classmates content"
// @Success 200 {object} models.Classmates
// @Failure 403 :id is not int
// @router /:id [put]
func (c *ClassmatesController) Put() {
	idStr := c.Ctx.Input.Param(":id")
	id, _ := strconv.Atoi(idStr)
	v := models.Classmates{Id: id}
	var export models.Export
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil {
		if err := models.UpdateClassmatesById(&v); err == nil {
			export.Code = 1000
			export.Message = "修改成功"
			c.Data["json"] = export
		} else {
			export.Code = 1001
			export.Message = err.Error()
			c.Data["json"] = export
		}
	} else {
		export.Code = 1002
		export.Message = err.Error()
		c.Data["json"] = export
	}
	c.ServeJSON()
}

// Delete ...
// @Title Delete
// @Description 删除指定的学生
// @Param	id		path 	string	true		"你需要删除的学生的id"
// @Success 200 {string} delete success!
// @Failure 403 id is empty
// @router /:id [delete]
func (c *ClassmatesController) Delete() {
	idStr := c.Ctx.Input.Param(":id")
	id, _ := strconv.Atoi(idStr)
	var export models.Export
	if code, err := models.DeleteClassmates(id); err == nil {
		export.Code = code
		if code == 1000 {
			export.Message = "删除成功"
		} else {
			export.Message = err.Error()
		}
		c.Data["json"] = export
	} else {
		export.Code = code
		export.Message = err.Error()
		c.Data["json"] = export
	}
	c.ServeJSON()
}

// 登录 ...
// @Title 登录
// @Description 学生登录
// @Param	sn		query 	string	true		"学号"
// @Param	pswd		query 	string	true		"密码"
// @Success 200 {string} delete success!
// @Failure 403 id is empty
// @router /login [get]
func (c *ClassmatesController) Login() {
	var sn = c.GetString("sn")
	var pswd = c.GetString("pswd")
	// 控制器   控制流程的
	result, err := models.Login(sn, pswd)
	// 1. 如果是错误的情况下 要输出 错误的原因
	// 2. 如果是正确的情况下，要输出 正确的数据
	var export models.Export
	if result == nil {
		export.Code = 1001
		export.Message = err.Error()
	} else {
		export.Code = 1000
		export.Message = "登录成功"
		export.Data = result
	}
	c.Data["json"] = export
	c.ServeJSON()
}

// 转账函数 ...
// @Title 转账函数
// @Description 转账函数
// @Param	id		query 	int	true		"收款人的id"
// @Param	money		query 	float32	true		"转账数额"
// @Success 200 {string} delete success!
// @Failure 403 id is empty
// @router /zhuanzhang [get]
func (c *ClassmatesController) ZhuanZhang() {
	// 1. 获取参数
	receiveid, _ := c.GetInt("id")
	money, _ := c.GetFloat("money", 0)
	// 从过滤器里面 拿到身份信息
	jwtObj := c.Ctx.Input.GetData("jwt")
	var export models.Export
	if jwtObj == nil {
		export.Code = 1002
		export.Message = "没有登录信息"
		c.Data["json"] = export
		c.ServeJSON()
		return
	}
	// 转换成 jwt格式
	jwt := jwtObj.(*models.Claims)
	// fromid  是一个当前登录用户的id ，而不是随便填的。
	// 2. 调用业务处理
	// 业务处理  一般都放在 models包里面
	result := models.ZhuanZhang(jwt.UserID, receiveid, money)

	if result == false {
		export.Code = 1001
		export.Message = "转账失败"
		export.Data = result
	} else {
		export.Code = 1000
		export.Message = "转账成功"
		export.Data = result
	}
	// 3.输出给前端
	c.Data["json"] = export
	c.ServeJSON()
}

// 修改密码 ...
// @Title 修改密码
// @Description 修改密码
// @Param	userid		query 	int	true		"用户id"
// @Param	oldpswd		query 	string	true		"旧密码"
// @Param	newpswd		query 	string	true		"新密码"
// @Success 200 {string} delete success!
// @Failure 403 id is empty
// @router /updatepswd [post]
func (c *ClassmatesController) UpdatePswd() {
	// 接收参数
	var oldpswd = c.GetString("oldpswd")
	var newpswd = c.GetString("newpswd")
	var userid, _ = c.GetInt("userid")
	// 调用models里的函数 进行业务处理
	result := models.Updatepswd(userid, oldpswd, newpswd)
	var export models.Export
	// 输出处理结果给前端
	if result == false {
		export.Code = 1002
		export.Message = "密码修改失败"
		c.Data["json"] = export
		c.ServeJSON()
		return
	}
	export.Code = 1000
	export.Message = "密码修改成功"
	c.Data["json"] = export
	c.ServeJSON()

}

// 发邮件 ...
// @Title Websocket
// @Description Websocket
// @Success 200 {string} delete success!
// @Failure 403 id is empty
// @router /websocket [get]
func (c *ClassmatesController) Websocket() {
	var upgrader = websocket.Upgrader{} // 定义upgrader变量
	conn, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	for i := 0; i < 100; i++ {
		if err := conn.WriteMessage(1, []byte("我收到的是"+strconv.Itoa(i))); err != nil {
			log.Println(err)
			return
		}
		time.Sleep(1 * time.Second)
	}
}

// 上传头像 ...
// @Title UploadFace
// @Description create Classmates
// @Param	uploadname 	query 	string	true		"文件名"
// @Success 201 {int} models.Classmates
// @Failure 403 body is empty
// @router / upload/face [post]
func (c *ClassmatesController) UploadFace() {
	var export models.Export
	f, h, err := c.GetFile("uploadname")
	if err != nil {
		export.Code = 1002
		export.Message = "上传失败"
		export.Data = err
		c.Data["json"] = export
		c.ServeJSON()
		return
	}
	defer f.Close()
	name := strings.Split(h.Filename, ".")
	ext := name[len(name)-1]
	switch ext {
	case "exe":
		fallthrough
	case "sh":
		fallthrough
	case "bat":
		export.Code = 1002
		export.Message = "上传失败"
		export.Data = err
		c.Data["json"] = export
		c.ServeJSON()
		return
	}
	newFilname := time.Now().Format("2006010215040512345") + "." + ext
	c.SaveToFile("uploadname", "./static/images/"+newFilname)
	export.Code = 1000
	export.Message = "上传成功"
	c.Data["json"] = export
	c.ServeJSON()
}
